/*
 * This file is part of aion-lightning <aion-lightning.org>.
 * 
 * aion-lightning is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * aion-lightning is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with aion-lightning.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.aionengine.gameserver.controllers.movement;

import com.aionengine.gameserver.ai2.AISubState;
import com.aionengine.gameserver.model.gameobjects.Summon;
import com.aionengine.gameserver.network.aion.serverpackets.SM_MOVE;
import com.aionengine.gameserver.taskmanager.tasks.MoveTaskManager;
import com.aionengine.gameserver.utils.MathUtil;
import com.aionengine.gameserver.utils.PacketSendUtility;
import com.aionengine.gameserver.world.World;

/**
 * @author xTz
 */
public class SiegeWeaponMoveController extends SummonMoveController {

    private float pointX;
    private float pointY;
    private float pointZ;
    private float offset = 0.1f;
    public static final float MOVE_CHECK_OFFSET = 0.1f;

    public SiegeWeaponMoveController(Summon owner) {
        super(owner);
    }

    /**
     * @return if destination reached
     */
    @Override
    public void moveToDestination() {
        if (!owner.canPerformMove() || (owner.getAi2().getSubState() == AISubState.CAST)) {
            if (started.compareAndSet(true, false)) {
                setAndSendStopMove(owner);
            }
            updateLastMove();
            return;
        } else if (started.compareAndSet(false, true)) {
            movementMask = -32;
            PacketSendUtility.broadcastPacket(owner, new SM_MOVE(owner));
        }

        if (MathUtil.getDistance(owner.getTarget(), pointX, pointY, pointZ) > MOVE_CHECK_OFFSET) {
            pointX = owner.getTarget().getX();
            pointY = owner.getTarget().getY();
            pointZ = owner.getTarget().getZ();
        }
        moveToLocation(pointX, pointY, pointZ, offset);
        updateLastMove();
    }

    @Override
    public void moveToTargetObject() {
        updateLastMove();
        MoveTaskManager.getInstance().addCreature(owner);
    }

    /**
     * @param targetX
     * @param targetY
     * @param targetZ
     * @param offset
     * @return
     */
    protected void moveToLocation(float targetX, float targetY, float targetZ, float offset) {
        boolean directionChanged;
        float ownerX = owner.getX();
        float ownerY = owner.getY();
        float ownerZ = owner.getZ();

        directionChanged = targetX != targetDestX || targetY != targetDestY || targetZ != targetDestZ;

        if (directionChanged) {
            heading = (byte) (Math.toDegrees(Math.atan2(targetY - ownerY, targetX - ownerX)) / 3);
        }

        targetDestX = targetX;
        targetDestY = targetY;
        targetDestZ = targetZ;

        float currentSpeed = owner.getGameStats().getMovementSpeedFloat();
        float futureDistPassed = currentSpeed * (System.currentTimeMillis() - lastMoveUpdate) / 1000f;

        float dist = (float) MathUtil.getDistance(ownerX, ownerY, ownerZ, targetX, targetY, targetZ);

        if (dist == 0) {
            return;
        }

        if (futureDistPassed > dist) {
            futureDistPassed = dist;
        }

        float distFraction = futureDistPassed / dist;
        float newX = (targetDestX - ownerX) * distFraction + ownerX;
        float newY = (targetDestY - ownerY) * distFraction + ownerY;
        float newZ = (targetDestZ - ownerZ) * distFraction + ownerZ;
        World.getInstance().updatePosition(owner, newX, newY, newZ, heading, false);
        if (directionChanged) {
            movementMask = -32;
            PacketSendUtility.broadcastPacket(owner, new SM_MOVE(owner));
        }
    }

}
